Skip to content

fix: composite RGBA onto background in loadCam for NeRF Synthetic data#1320

Open
Flocio wants to merge 1 commit into
graphdeco-inria:mainfrom
Flocio:fix-nerf-synthetic-rgba-bg
Open

fix: composite RGBA onto background in loadCam for NeRF Synthetic data#1320
Flocio wants to merge 1 commit into
graphdeco-inria:mainfrom
Flocio:fix-nerf-synthetic-rgba-bg

Conversation

@Flocio
Copy link
Copy Markdown

@Flocio Flocio commented Mar 17, 2026

The Aug 2024 refactor removed the image field from CameraInfo, but loadCam reads raw RGBA from disk without alpha compositing. This causes training to mask rendered background via alpha_mask while evaluation does not, leading to PSNR ~2-3 on Blender scenes. Restore compositing in loadCam to match the behavior of readCamerasFromTransforms.

Summary

This PR fixes a regression in the NeRF Synthetic data path when using RGBA images (Blender renders) together with --white_background (or black background). After a refactor, the RGBA → RGB compositing step that was present in the older implementation was dropped from the actual loadCam path, which leads to incorrect backgrounds and slightly wrong metrics on NeRF Synthetic, while COLMAP-based datasets remain unaffected.

Bug

  • Affects only NeRF Synthetic datasets (Blender) when images are RGBA.
  • In previous versions, RGBA images were composited onto a solid white/black background before being passed to the rest of the pipeline.
  • After the data loading refactor, loadCam no longer performs this compositing, so:
    • Background pixels are not correctly composited (e.g., gray/black halos with --white_background).
    • Training and evaluation use alpha masks in a way that no longer matches the original behavior, which also changes PSNR slightly compared to the reference implementation.

Fix

Re-introduce RGBA → RGB compositing in loadCam for the NeRF Synthetic RGBA case:

if is_nerf_synthetic and image.mode == "RGBA":
    bg = np.array([1, 1, 1]) if args.white_background else np.array([0, 0, 0])
    im_data = np.array(image).astype(np.float32) / 255.0
    arr = im_data[:, :, :3] * im_data[:, :, 3:4] + bg * (1 - im_data[:, :, 3:4])
    image = Image.fromarray((arr * 255).astype(np.uint8), "RGB")

This matches the alpha compositing logic that previously lived in dataset_readers.py (using the standard RGB * alpha + bg * (1 - alpha) formula), but applies it on the current loadCam code path where images are actually loaded now.

After this compositing, Camera.__init__ only sees RGB images and alpha_mask falls back to all ones, which is consistent with the original behavior where both training and evaluation operate on a solid background image.

Safety

The change is guarded by two conditions:

  • is_nerf_synthetic == True
  • image.mode == "RGBA"

Therefore:

  • COLMAP datasets (Tanks&Temples, MipNeRF360, Deep Blending, etc.) are not affected (is_nerf_synthetic is false).
  • NeRF Synthetic images that are already RGB are not affected (image.mode != "RGBA").

Validation

  • Tested on NeRF Synthetic (e.g., Lego) with --white_background:
    • Background appearance matches the older implementation (no gray/black halos).
    • PSNR returns to the expected values from the reference code.
  • Tested on a COLMAP-based scene to confirm no change in behavior.

The Aug 2024 refactor removed the image field from CameraInfo, but loadCam reads raw RGBA from disk without alpha compositing. This causes training to mask rendered background via alpha_mask while evaluation does not, leading to PSNR ~2-3 on Blender scenes. Restore compositing in loadCam to match the behavior of readCamerasFromTransforms.
@zcemcui
Copy link
Copy Markdown

zcemcui commented Apr 9, 2026

Have the same issue, problem has been solved. Love it !!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants